package com.lemon.cloud.extension;

import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author lemon
 * @version 1.0
 * @description: TODO
 * @date Create by lemon on 2019-09-14 18:10
 */
public abstract class AbstractExtensionExecutor {
    /**
     * @param targetClass
     * @param businessScenario
     * @param executeExtensionPoint
     * @return R
     * @description
     * @author lemon
     * @date 2019-09-14 22:04
     */
    public <R, T> R execute(Class<T> targetClass, BusinessScenario businessScenario, Function<T, R> executeExtensionPoint) {
        T component = locateExtensionPoint(targetClass, businessScenario);
        return executeExtensionPoint.apply(component);
    }

    /**
     * @param extensionCoordinate
     * @param executeExtensionPoint
     * @return R
     * @description
     * @author lemon
     * @date 2019-09-14 22:04
     */
    public <R, T> R execute(ExtensionCoordinate extensionCoordinate, Function<T, R> executeExtensionPoint) {
        return execute((Class<T>) extensionCoordinate.getExtensionPointClass(), extensionCoordinate.getBusinessScenario(), executeExtensionPoint);
    }

    /**
     * @param targetClass
     * @param businessScenario
     * @param executeExtensionPoint
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-14 22:04
     */
    public <T> void executeVoid(Class<T> targetClass, BusinessScenario businessScenario, Consumer<T> executeExtensionPoint) {
        T component = locateExtensionPoint(targetClass, businessScenario);
        executeExtensionPoint.accept(component);
    }

    /**
     * @param extensionCoordinate
     * @param executeExtensionPoint
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-14 22:04
     */
    public <T> void executeVoid(ExtensionCoordinate extensionCoordinate, Consumer<T> executeExtensionPoint) {
        executeVoid(extensionCoordinate.getExtensionPointClass(), extensionCoordinate.getBusinessScenario(), executeExtensionPoint);
    }

    /**
     * @param extensionPointClass
     * @param businessScenario
     * @return C
     * @description
     * @author lemon
     * @date 2019-09-14 22:04
     */
    protected abstract <C> C locateExtensionPoint(Class<C> extensionPointClass, BusinessScenario businessScenario);
}
